package huriezy.quickcontacts.activities.fragments;

import huriezy.quickcontacts.R;
import huriezy.quickcontacts.models.ContactController;
import huriezy.quickcontacts.models.LogDebug;
import huriezy.quickcontacts.models.interfaces.IContactManager;
import huriezy.quickcontacts.models.interfaces.IPictureManager;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;

import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.provider.MediaStore;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;

public class PictureFragment extends ContactFragment {

	private final String		autoCropPref					= "auto_crop_pref";

	private static final int	REQUEST_CAMERA_PICTURE_CODE		= 8426;
	private static final int	REQUEST_CROPPED_PICTURE_CODE	= 2684;
	private static final int	REQUEST_GALLERY_PICTURE_CODE	= 8624;

	private String				currentPictureFilepath;
	private IPictureManager		contactPictureManager;

	public static PictureFragment newInstance(String filepath) {
		PictureFragment instance = new PictureFragment();
		if (filepath != null) {
			Bundle args = new Bundle();
			args.putString(IContactManager.PICTURE_TAG, filepath);
			instance.setArguments(args);
		}
		return instance;
	}

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
		super.onCreateView(inflater, container, savedInstanceState);
		View result = inflater.inflate(R.layout.fragment_picture, container, false);
		Bundle args = getArguments();
		if (args != null) {
			currentPictureFilepath = args.getString(IContactManager.PICTURE_TAG);
			if (currentPictureFilepath != null && currentPictureFilepath.length() > 0) {
				LogDebug.info(" * Use new InstanceState for " + getClass().getSimpleName() + ", current path : "
						+ currentPictureFilepath, getClass());
			}
		}
		if (currentPictureFilepath == null || currentPictureFilepath.length() <= 0) {
			args = savedInstanceState;
			if (args != null) {
				currentPictureFilepath = args.getString(IContactManager.PICTURE_TAG);
				if (currentPictureFilepath != null && currentPictureFilepath.length() > 0) {
					LogDebug.info(" * Use savedInstanceState for " + getClass().getSimpleName() + ", current path : "
							+ currentPictureFilepath, getClass());
				}
			}
		}

		contactPictureManager = ContactController.getInstance().getPictureManager(getActivity());
		initActions(result);

		return result;
	}

	@Override
	public void onStart() {
		super.onStart();
		if (currentPictureFilepath != null && currentPictureFilepath.length() > 0) {
			loadContactPicture(currentPictureFilepath, getView());
		}
		else {
			LogDebug.warn("No saved informations inside the used bundle.", getActivity());
		}

	}

	@Override
	public void updateData() {
		LogDebug.info("update data in Picturefragment", getClass());
		IContactManager contactManager = ContactController.getInstance().getContactManager(getActivity());
		String pictureSaved = contactManager.getContactData(IContactManager.PICTURE_TAG);
		LogDebug.info("Current filepath : " + currentPictureFilepath, getClass());
		LogDebug.info("Saved filepath : " + pictureSaved, getClass());
		if (pictureSaved != null && !pictureSaved.equals(currentPictureFilepath)) {
			currentPictureFilepath = pictureSaved;
			loadContactPicture(currentPictureFilepath, getView());
		}
	}

	public void saveContactData() {
		IContactManager contactManager = ContactController.getInstance().getContactManager(getActivity());
		contactManager.putContactData(IContactManager.PICTURE_TAG, currentPictureFilepath);
	}

	@Override
	public void clearContactData() {
		currentPictureFilepath = "";
		Bundle arguments = getArguments();
		if (arguments != null) {
			arguments.putString(IContactManager.PICTURE_TAG, currentPictureFilepath);
		}
		loadContactPicture(currentPictureFilepath, getView());
	}

	@Override
	public void onSaveInstanceState(Bundle outState) {
		outState.putString(IContactManager.PICTURE_TAG, currentPictureFilepath);
		LogDebug.info("Path on save instance : " + currentPictureFilepath, getClass());
		super.onSaveInstanceState(outState);
	}

	@Override
	public void onStop() {
		Bundle args = getArguments();
		if (args != null) {
			args.putString(IContactManager.PICTURE_TAG, currentPictureFilepath);
		}
		LogDebug.info("Current path : " + currentPictureFilepath, getClass());
		super.onStop();
	}

	/**
	 * Load the saved bitmap picture into the contact {@link ImageView} of this
	 * fragment view.
	 * 
	 * @param args
	 * @param container
	 */
	private void loadContactPicture(String pictureLocation, View container) {
		if (pictureLocation != null && container != null) {
			Bitmap bitmapPicture = null;
			File file = new File(pictureLocation);
			if (file.isFile()) {
				bitmapPicture = BitmapFactory.decodeFile(pictureLocation);
			}
			ImageView userImageView = (ImageView) container.findViewById(R.id.new_user_imageView);
			if (userImageView != null) {
				if (bitmapPicture != null) {
					userImageView.setImageBitmap(bitmapPicture);
					currentPictureFilepath = pictureLocation;
					LogDebug.info("Loaded bitmap image located at : " + pictureLocation, getClass());
				}
				else {
					Drawable defaultUser = getResources().getDrawable(R.drawable.ic_default_user);
					userImageView.setImageDrawable(defaultUser);
				}
			}
		}
	}

	private void initActions(View parentView) {
		final Activity parentActivity = getActivity();
		final PackageManager packageManager = parentActivity.getPackageManager();

		// Implements camera button associated action
		Button cameraImageView = (Button) parentView.findViewById(R.id.use_camera_button);
		if (cameraImageView != null) {
			if (packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
				cameraImageView.setOnClickListener(new OnClickListener() {
					@Override
					public void onClick(View v) {
						PackageManager packageManager = parentActivity.getPackageManager();
						Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
						if (takePictureIntent.resolveActivity(packageManager) != null) {
							startActivityForResult(takePictureIntent, REQUEST_CAMERA_PICTURE_CODE);
						}
					}
				});
			}
			else {
				cameraImageView.setVisibility(View.GONE);
			}
		}
		else {
			LogDebug.warn("Cannot find camera button", getActivity());
		}

		// Creates listener for image picking intent
		OnClickListener listener = new OnClickListener() {
			@Override
			public void onClick(View v) {
				Intent galleryIntent = new Intent(Intent.ACTION_GET_CONTENT);
				galleryIntent.setType("image/*");
				if (galleryIntent.resolveActivity(packageManager) != null) {
					startActivityForResult(galleryIntent, REQUEST_GALLERY_PICTURE_CODE);
				}
			}
		};

		// Implements gallery chooser button
		Button galleryButton = (Button) parentView.findViewById(R.id.use_gallery_button);
		if (galleryButton != null) {
			galleryButton.setOnClickListener(listener);
		}
		else {
			LogDebug.warn("Cannot find gallery button", getActivity());
		}

		// Implements user picture view reaction to click
		ImageView userImageView = (ImageView) parentView.findViewById(R.id.new_user_imageView);
		if (userImageView != null) {
			userImageView.setOnClickListener(listener);
		}
		else {
			LogDebug.warn("Cannot find new user picture view", getActivity());
		}
	}

	@Override
	public void onActivityResult(int requestCode, int resultCode, Intent data) {
		final Activity parentActivity = getActivity();
		ImageView userImageView = (ImageView) parentActivity.findViewById(R.id.new_user_imageView);
		SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
		boolean autoCrop = false;
		if (preferences != null) {
			autoCrop = preferences.getBoolean(autoCropPref, false);
		}
		if (resultCode == Activity.RESULT_OK && userImageView != null) {
			Bitmap bitmapResult = null;
			Uri pictureUri = null;
			if (requestCode == REQUEST_CAMERA_PICTURE_CODE || requestCode == REQUEST_GALLERY_PICTURE_CODE) {
				LogDebug.info("Request code = " + requestCode, getClass());
				pictureUri = data.getData();
				if (!autoCrop) {
					try {
						performCrop(pictureUri);
					}
					catch (ActivityNotFoundException error) {
						LogDebug.error("Crop action cannot be done using this device", getActivity(), error);
						autoCrop = true;
					}
				}
				if (autoCrop) {
					LogDebug.info("Auto-crop image in location '" + pictureUri + "'", getClass());
					try {
						bitmapResult = contactPictureManager.scaleImage(pictureUri);
					}
					catch (FileNotFoundException error) {
						LogDebug.error("File not found for " + pictureUri.getPath(), getClass());
					}
					catch (IOException error) {
						LogDebug.error("Input stream error", getClass());
					}
					if (bitmapResult != null) {
						LogDebug.info("setImageBitmap : " + bitmapResult.getWidth() + "," + bitmapResult.getHeight(),
								getClass());

						userImageView.setImageBitmap(bitmapResult);
						currentPictureFilepath = pictureUri.getPath();
					}
					else {
						LogDebug.warn("Cannot use bitmap image, cause : the bitmap object is null", getActivity());
					}
				}
			}
			else if (requestCode == REQUEST_CROPPED_PICTURE_CODE) {
				Bundle extras = data.getExtras();
				bitmapResult = extras.getParcelable("data");
				File resultFile = contactPictureManager.saveTempImageFile(bitmapResult);
				currentPictureFilepath = resultFile.getAbsolutePath();
				userImageView.setImageBitmap(bitmapResult);
			}
		}
	}

	/**
	 * Send an {@link Intent} asking for cropping the picture located at the
	 * {@link Uri} parameter location.
	 * 
	 * @param pictureUri
	 *            the concerned {@link Uri}
	 * @throws ActivityNotFoundException
	 */
	private void performCrop(Uri pictureUri) throws ActivityNotFoundException {
		Intent cropIntent = new Intent("com.android.camera.action.CROP");
		cropIntent.setDataAndType(pictureUri, "image/*");
		cropIntent.putExtra("crop", "true");
		cropIntent.putExtra("aspectX", 1);
		cropIntent.putExtra("aspectY", 1);
		cropIntent.putExtra("outputX", 256);
		cropIntent.putExtra("outputY", 256);
		cropIntent.putExtra("return-data", true);
		startActivityForResult(cropIntent, REQUEST_CROPPED_PICTURE_CODE);
	}

}
